1   /*
2    * Copyright (C) 2007 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import com.google.common.collect.MapConstraints.ConstrainedMap;
20  import com.google.common.primitives.Primitives;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  /**
26   * A mutable class-to-instance map backed by an arbitrary user-provided map.
27   * See also {@link ImmutableClassToInstanceMap}.
28   * 
29   * <p>See the Guava User Guide article on <a href=
30   * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#ClassToInstanceMap">
31   * {@code ClassToInstanceMap}</a>.
32   *
33   * @author Kevin Bourrillion
34   * @since 2.0 (imported from Google Collections Library)
35   */
36  public final class MutableClassToInstanceMap<B>
37      extends ConstrainedMap<Class<? extends B>, B>
38      implements ClassToInstanceMap<B> {
39  
40    /**
41     * Returns a new {@code MutableClassToInstanceMap} instance backed by a {@link
42     * HashMap} using the default initial capacity and load factor.
43     */
44    public static <B> MutableClassToInstanceMap<B> create() {
45      return new MutableClassToInstanceMap<B>(
46          new HashMap<Class<? extends B>, B>());
47    }
48  
49    /**
50     * Returns a new {@code MutableClassToInstanceMap} instance backed by a given
51     * empty {@code backingMap}. The caller surrenders control of the backing map,
52     * and thus should not allow any direct references to it to remain accessible.
53     */
54    public static <B> MutableClassToInstanceMap<B> create(
55        Map<Class<? extends B>, B> backingMap) {
56      return new MutableClassToInstanceMap<B>(backingMap);
57    }
58  
59    private MutableClassToInstanceMap(Map<Class<? extends B>, B> delegate) {
60      super(delegate, VALUE_CAN_BE_CAST_TO_KEY);
61    }
62  
63    private static final MapConstraint<Class<?>, Object> VALUE_CAN_BE_CAST_TO_KEY
64        = new MapConstraint<Class<?>, Object>() {
65      @Override
66      public void checkKeyValue(Class<?> key, Object value) {
67        cast(key, value);
68      }
69    };
70  
71    @Override
72    public <T extends B> T putInstance(Class<T> type, T value) {
73      return cast(type, put(type, value));
74    }
75  
76    @Override
77    public <T extends B> T getInstance(Class<T> type) {
78      return cast(type, get(type));
79    }
80  
81    private static <B, T extends B> T cast(Class<T> type, B value) {
82      return Primitives.wrap(type).cast(value);
83    }
84  
85    private static final long serialVersionUID = 0;
86  }